package com.quiz.file.service.impl;

import com.quiz.common.core.redis.RedisCache;
import com.quiz.common.exception.ServiceException;
import com.quiz.file.domain.model.FileInfo;
import com.quiz.file.service.IFileService;
import com.quiz.file.service.IFileTokenService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 文件服务令牌实现类
 *
 * @author ahuan
 */
@Service
@RequiredArgsConstructor
public class FileTokenServiceImpl implements IFileTokenService {

    private final String secret = "quiz.file.token.161dasf51516a3df1";

    private final RedisCache redisCache;

    private final IFileService fileService;

    @Override
    public String createToken(Long fileId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("fileId", fileId);
        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, secret).compact();
    }

    @Override
    public String createToken(String fileId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("fileId", fileId);
        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, secret).compact();
    }

    @Override
    public void verifyToken(String token) {
        try {
            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
        } catch (Exception e) {
            throw new RuntimeException("文件token验证失败");
        }
    }

    @Override
    public void refreshToken(String token) {

//        try {
//            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
//        } catch (Exception e) {
//            throw new RuntimeException("文件token验证失败");
//        }

    }

    @Override
    public void delToken(String token) {
        redisCache.deleteObject(token);
    }

    @Override
    public long[] getFileIds(String token) {
        try {
            String fileId = parseToken(token).get("fileId", String.class);
            return Arrays.stream(fileId.split(",")).mapToLong(Long::parseLong).toArray();
        } catch (Exception e) {
            throw new RuntimeException("文件token验证失败");
        }
    }

    @Override
    public long getFileId(String token) {
        try {
            Claims claims = parseToken(token);
            String s = claims.get("fileId", String.class);
            long l = Long.parseLong(s);

            return l;
        } catch (Exception e) {
            throw new RuntimeException("文件token验证失败");
        }
    }

    @Override
    public List<FileInfo> getFileInfos(String token) {
        long[] fileId = getFileIds(token);
        return fileService.getFileByIds(fileId);
    }

    @Override
    public FileInfo getFileInfo(String token, String fileId) {
        Claims claims = parseToken(token);
        String[] ids = claims.get("fileId", String.class).split(",");
        if (Arrays.stream(ids).noneMatch(s -> s.equals(fileId))) {
            throw new ServiceException("文件token验证失败");
        }
        return fileService.getFileById(Long.parseLong(fileId));
    }


    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }
}
